using Domain.Entities;
using Domain.Entities.Enums;
using Domain.Misc;
using NHibernate;
using NHibernate.Expression;
using System;
using System.Collections.Generic;

namespace Domain.Services
{
    public static class UserService
    {
        /*****************************************************************************************
        * Getters
        * ***************************************************************************************/
        public static IList<User> GetAll()
        {
            ISession session = NHibernateHelper.Instance.CurrentSession;
            return session.CreateCriteria(typeof(User)).AddOrder(Order.Asc("Username")).List<User>();
        }

        public static IList<User> GetAwaitingAdminActivation()
        {
            ISession session = NHibernateHelper.Instance.CurrentSession;
            return session.CreateQuery("from User u where u.Status = 3").List<User>();
        }

        public static User GetById(int userId)
        {
            ISession session = NHibernateHelper.Instance.CurrentSession;
            return session.Get<User>(userId);
        }

        public static Permission GetPermissions(short forumId, int userId)
        {
            ISession session = NHibernateHelper.Instance.CurrentSession;

            Permission allPermissions = Permission.None;
            User user = session.Get<User>(userId);

            foreach (Group group in user.Groups)
            {
                foreach (GroupForumPermission groupForumPermission in group.GroupForumPermission)
                {
                    if (groupForumPermission.Forum.Id == forumId)
                    {
                        allPermissions |= groupForumPermission.Permissions;
                    }
                }
            }

            foreach (UserForumPermission userForumPermission in user.UserForumPermissions)
            {
                if (userForumPermission.Forum.Id == forumId)
                {
                    allPermissions |= userForumPermission.Permissions;
                }
            }

            return allPermissions;
        }

        public static User GetByUsernameAndPassword(string username, string password)
        {
            ISession session = NHibernateHelper.Instance.CurrentSession;
            return session.CreateQuery("from User u where u.Username = '" + username + "' and u.Password = '" + password + "'").UniqueResult<User>();
        }

        public static User GetByIdAndActivationKey(int id, string activationKey)
        {
            ISession session = NHibernateHelper.Instance.CurrentSession;
            return session.CreateQuery("from User u where u.Id = '" + id + "' and u.ActivationKey = '" + activationKey + "'").UniqueResult<User>();
        }

        public static User GetByUsernameAndEmail(string username, string email)
        {
            ISession session = NHibernateHelper.Instance.CurrentSession;
            return session.CreateQuery("from User u where u.Username = '" + username + "' and u.Email = '" + email + "'").UniqueResult<User>();
        }

        public static User GetByIdAndPassword(int id, string password)
        {
            ISession session = NHibernateHelper.Instance.CurrentSession;
            return session.CreateQuery("from User u where u.Id = '" + id + "' and u.Password = '" + password + "'").UniqueResult<User>();
        }

        public static User GetByUsername(string username)
        {
            ISession session = NHibernateHelper.Instance.CurrentSession;
            return session.CreateQuery("from User u where u.Username = '" + username + "'").UniqueResult<User>();
        }

        public static IList<User> GetMatchingUsername(string term)
        {
            ISession session = NHibernateHelper.Instance.CurrentSession;
            return session.CreateQuery("from User u where u.Username like '" + term + "'").List<User>();
        }

        public static int GetTotalNumberOfUsers()
        {
            string query = "select count(*) from User user";
            return NHibernateHelper.CountQuery(query);
        }

        /*****************************************************************************************
        * Adders
        * ***************************************************************************************/
        public static User NewUser(string username, string email, string password, UserStatus status, IList<Group> groups)
        {
            ISession session = NHibernateHelper.Instance.CurrentSession;
            using (ITransaction transaction = session.BeginTransaction())
            {
                User user = new User();
                user.RegisterDateTime = DateTime.Now;
                user.LastActiveDateTime = DateTime.Now;
                user.Status = status;
                user.Username = username;
                user.Password = password;
                if (status == UserStatus.AwaitingActivationByEmail || status == UserStatus.Reserved)
                {
                    user.ActivationKey = RandomStringGenerator.Generate(32);
                }
                user.Email = email;
                user.FirstName = "";
                user.LastName = "";
                user.Birthdate = DateTime.Now;
                user.Location = "";
                user.WebsiteUrl = "";
                user.AvatarUrl = "";
                user.Signature = "";
                user.BBCodeByDefault = true;
                user.EmoticonsByDefault = true;
                user.DisplaySignatureByDefault = true;
                user.TopicsPerPage = 0;
                user.MessagesPerPage = 0;
                if (groups != null)
                {
                    user.Groups = groups;
                }
                session.SaveOrUpdate(user);

                transaction.Commit();

                return user;
            }
        }

        /*****************************************************************************************
        * Updaters
        * ***************************************************************************************/
        public static void UpdateGroups(User user, IList<Group> groups)
        {
            ISession session = NHibernateHelper.Instance.CurrentSession;
            using (ITransaction transaction = session.BeginTransaction())
            {
                user.Groups = groups;
                session.SaveOrUpdate(user);

                transaction.Commit();
            }
        }

        public static void UpdateLastActiveDateTime(User user, DateTime lastActiveDateTime)
        {
            ISession session = NHibernateHelper.Instance.CurrentSession;
            using (ITransaction transaction = session.BeginTransaction())
            {
                user.LastActiveDateTime = lastActiveDateTime;
                session.SaveOrUpdate(user);

                transaction.Commit();
            }
        }

        public static void UpdatePassword(User user, string password)
        {
            ISession session = NHibernateHelper.Instance.CurrentSession;
            using (ITransaction transaction = session.BeginTransaction())
            {
                user.Password = password;
                session.SaveOrUpdate(user);

                transaction.Commit();
            }
        }

        public static void UpdateStatus(User user, UserStatus status)
        {
            ISession session = NHibernateHelper.Instance.CurrentSession;
            using (ITransaction transaction = session.BeginTransaction())
            {
                user.Status = status;
                if (status == UserStatus.RetrievingPassword)
                {
                    user.ActivationKey = RandomStringGenerator.Generate(32);
                }
                else if (status == UserStatus.Activated || status == UserStatus.AwaitingActivationByAdmin || status == UserStatus.DeniedByAdmin || status == UserStatus.Disabled || status == UserStatus.Reserved)
                {
                    user.ActivationKey = null;
                }
                session.SaveOrUpdate(user);

                transaction.Commit();
            }
        }

        public static void UpdateUser
        (
            User user, 
            string email,
            string firstName, 
            string lastName, 
            Gender gender, 
            DateTime dateTime, 
            string websiteUrl, 
            string avatarUrl, 
            string signature,
            Theme theme, 
            byte topicsPerPage,
            byte messagesPerPage
        )
        {
            ISession session = NHibernateHelper.Instance.CurrentSession;
            using (ITransaction transaction = session.BeginTransaction())
            {
                user.Email = email;
                user.FirstName = firstName;
                user.LastName = lastName;
                user.Gender = gender;
                user.Birthdate = dateTime;
                user.WebsiteUrl = websiteUrl;
                user.AvatarUrl = avatarUrl;
                user.Signature = signature;
                user.TopicsPerPage = topicsPerPage;
                user.MessagesPerPage = messagesPerPage;
                user.Theme = theme;

                session.SaveOrUpdate(user);

                transaction.Commit();
            }
        }

        /*****************************************************************************************
        * Deleters
        * ***************************************************************************************/
        public static void RemoveUser(User user)
        {
            // TODO: implement
        }
    }
}
